package components.tree;

import java.beans.Beans;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

public class TreeFile extends JTree {
	private static final long serialVersionUID = 1L;

	private IFileWrapperLabel fileWrapperLabel;

	public TreeFile(File rootFile) {
		this(rootFile, true);
	}

	public TreeFile(File rootFile, boolean expandAll) {
		if(Beans.isDesignTime()){
			return;
		}
		setModel(createTreeModel(rootFile));
	}

	public void expandAll() {
		for (int i = 0; i < getRowCount(); i++) {
			expandRow(i);
		}
	}

	public TreePath find(File file) {
		@SuppressWarnings("unchecked")
		Enumeration<DefaultMutableTreeNode> e = ((DefaultMutableTreeNode) getModel().getRoot()).depthFirstEnumeration();
		while (e.hasMoreElements()) {
			DefaultMutableTreeNode node = e.nextElement();
			if (node.getUserObject().equals(new FileWrapper(file))) {
				return new TreePath(node.getPath());
			}
		}
		return null;
	}

	public File getFile(TreePath treePath) {
		if(treePath == null){
			return null;
		}
		
		DefaultMutableTreeNode node = ((DefaultMutableTreeNode) treePath.getLastPathComponent());

		FileWrapper fileWrapper = (FileWrapper) node.getUserObject();

		return fileWrapper.getFile();
	}

	public List<File> getFile(TreePath... treePath) {
		if (treePath == null) {
			return null;
		}
		List<File> files = new ArrayList<File>(treePath.length);

		for (int i = 0; i < treePath.length; i++) {
			File file = getFile(treePath[i]);
			if (file != null) {
				files.add(file);
			}
		}

		return files;
	}

	private TreeModel createTreeModel(File rootFile) {
		DefaultMutableTreeNode root = new DefaultMutableTreeNode(new FileWrapper(rootFile));
		createTreeNode(rootFile, root);
		TreeModel treeModel = new DefaultTreeModel(root, true);
		return treeModel;
	}

	private void createTreeNode(File rootFile, DefaultMutableTreeNode treeNodeParent) {

		if (rootFile.listFiles() != null) {
			for (File file : rootFile.listFiles()) {

				DefaultMutableTreeNode treeNodeChild = new DefaultMutableTreeNode(new FileWrapper(file), file.isDirectory());
				treeNodeParent.add(treeNodeChild);

				if (file.isDirectory()) {
					createTreeNode(file, treeNodeChild);
				}
			}
		}
	}

	public class FileWrapper {
		private File file;

		private String label;

		private FileWrapper(File file) {
			super();
			this.file = file;
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == null || !(obj instanceof FileWrapper)) {
				return false;
			}
			FileWrapper other = (FileWrapper) obj;

			return getFile().equals(other.getFile());
		}

		public File getFile() {
			return file;
		}

		@Override
		public String toString() {
			if (label == null) {
				label = fileWrapperLabel != null ? fileWrapperLabel.getLabel(file) : file.getName();
			}
			return label;
		}
	}

	public interface IFileWrapperLabel {
		String getLabel(File file);
	}
}
